﻿using System;
using System.IO;
using System.Xml.Serialization;
using Office = Microsoft.Office.DocumentManagement.DocumentSets;
using MS.InformationManagement.ContentHub.CustomFields;
using MS.InformationManagement.DAL.DocumentCenter;
using MS.InformationManagement.Support.Constants;
using MS.InformationManagement.Support.Enums;
using Microsoft.SharePoint;
using System.Xml;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint.Taxonomy;
using MS.InformationManagement.DAL.Support;
using MS.InformationManagement.ContentHub.ObjectDef.CustomFields;

namespace MS.InformationManagement.Core.Support
{
    public static class DocumentSetHelper
    {



        public static Office.DocumentSet GetDocumentSet(SPList list, int id)
        {
            var spFolder = list.GetItemById(id).Folder;
            var documentSet = Microsoft.Office.DocumentManagement.DocumentSets.DocumentSet.GetDocumentSet(spFolder);
            return documentSet;
        }

        public static SPListItemCollection getChildsFromDocumentSet(SPList list, string RadicadoID)
        {
            SPQuery query = new SPQuery();
            query.Query = string.Format("<Where><Eq><FieldRef Name='" + CustomSiteColumns.FIELD_DOCUMENT_RADICADO_PADRE + "'/><Value Type='Text'>{0}</Value></Eq></Where>", RadicadoID);
            var documents = list.GetItems(query);
            return documents;
        }



        public static void Log(this Office.DocumentSet documentSet, string subsection, DateTime entryDate, TraceableOperation operation
            , string user, string description)
        {
            XmlSerializer tSerializer = new XmlSerializer(typeof(TraceabilityEntry));
            StringWriter sWriter = new StringWriter();
            TraceabilityEntry entry = new TraceabilityEntry
            {
                Subsection = subsection,
                EntryDate = entryDate,
                Operation = operation,
                User = user,
                Description = description
            };

            tSerializer.Serialize(sWriter, entry);

            DocumentTraceabilityFieldValue traceabiltyFieldValue = documentSet.Folder.Item[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] as DocumentTraceabilityFieldValue;
            if (traceabiltyFieldValue == null) { traceabiltyFieldValue = new DocumentTraceabilityFieldValue(sWriter.ToString()); }
            else { traceabiltyFieldValue.Add(sWriter.ToString()); }
            documentSet.Folder.Item[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] = traceabiltyFieldValue;

        }

        public static void UpdateDeliveryLog(this Office.DocumentSet documentSet, DeliveryTraceabilityEntry deliveryLogEntry)
        {
            XmlSerializer tSerializer = new XmlSerializer(typeof(DeliveryTraceabilityEntry));
            StringWriter sWriter = new StringWriter();
            tSerializer.Serialize(sWriter, deliveryLogEntry);

            DeliveryTraceabilityFieldValue traceabiltyFieldValue = documentSet.Folder.Item[CustomSiteColumns.FIELD_DOCUMENT_DELIVERY_LOG] as DeliveryTraceabilityFieldValue;
            if (traceabiltyFieldValue == null)
                traceabiltyFieldValue = new DeliveryTraceabilityFieldValue(sWriter.ToString()); 
            else
                traceabiltyFieldValue.Add(sWriter.ToString()); 
            documentSet.Folder.Item[CustomSiteColumns.FIELD_DOCUMENT_DELIVERY_LOG] = traceabiltyFieldValue;
        }

        public static void UpdateDeliveryLog(this SPListItem item, DeliveryTraceabilityEntry deliveryLogEntry)
        {
            XmlSerializer tSerializer = new XmlSerializer(typeof(DeliveryTraceabilityEntry));
            StringWriter sWriter = new StringWriter();
            tSerializer.Serialize(sWriter, deliveryLogEntry);

            DeliveryTraceabilityFieldValue traceabiltyFieldValue = item[CustomSiteColumns.FIELD_DOCUMENT_DELIVERY_LOG] as DeliveryTraceabilityFieldValue;
            if (traceabiltyFieldValue == null)
                traceabiltyFieldValue = new DeliveryTraceabilityFieldValue(sWriter.ToString());
            else
                traceabiltyFieldValue.Add(sWriter.ToString());
            item[CustomSiteColumns.FIELD_DOCUMENT_DELIVERY_LOG] = traceabiltyFieldValue;
        }

        public static IEnumerable<DeliveryTraceabilityEntry> GetDeliveryLog(this Office.DocumentSet input)
        {
            if (input.Folder.Item.Fields.GetFieldByInternalName(CustomSiteColumns.FIELD_DOCUMENT_DELIVERY_LOG) == null)
                return null;
            DeliveryTraceabilityFieldValue traceabiltyFieldValue = input.Item[CustomSiteColumns.FIELD_DOCUMENT_DELIVERY_LOG] as DeliveryTraceabilityFieldValue;
            return traceabiltyFieldValue == null ? null : traceabiltyFieldValue.Entries;
        }


        public static IEnumerable<TraceabilityEntry> GetLog(this Office.DocumentSet input)
        {
            DocumentTraceabilityFieldValue traceabiltyFieldValue = input.Item[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] as DocumentTraceabilityFieldValue;
            return traceabiltyFieldValue == null ? null : traceabiltyFieldValue.Entries;
        }

        public static void Log(this SPFile input,
                               string subsection,
                               DateTime entryDate,
                               TraceableOperation operation,
                               string user, string description)
        {
            XmlSerializer tSerializer = new XmlSerializer(typeof(TraceabilityEntry));
            StringWriter sWriter = new StringWriter();
            TraceabilityEntry entry = new TraceabilityEntry
            {
                Subsection = subsection,
                EntryDate = entryDate,
                Operation = operation,
                User = user,
                Description = description
            };

            tSerializer.Serialize(sWriter, entry);

            DocumentTraceabilityFieldValue traceabiltyFieldValue = input.Item[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] as DocumentTraceabilityFieldValue;
            if (traceabiltyFieldValue == null)
                traceabiltyFieldValue = new DocumentTraceabilityFieldValue(sWriter.ToString());
            else
                traceabiltyFieldValue.Add(sWriter.ToString());
            input.Item[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] = traceabiltyFieldValue;
        }


        public static void RemoveLog(this Office.DocumentSet input, DateTime entryDate)
        {
            removeDocumentLog(input.Folder.Item, entryDate);
        }

        public static void RemoveLog(this SPListItem input, DateTime entryDate)
        {
            removeDocumentLog(input, entryDate);               
        }

        public static void RemoveDeliveryLog(this SPListItem input, DateTime entryDate)
        {
            removeDeliveryLog(input, entryDate);
        }

        public static void RemoveDeliveryLog(this Office.DocumentSet input, DateTime entryDate)
        {
            removeDeliveryLog(input.Folder.Item, entryDate);
        }

        private static void removeDeliveryLog(SPListItem input, DateTime entryDate)
        {
            DeliveryTraceabilityFieldValue traceabiltyFieldValue = input[CustomSiteColumns.FIELD_DOCUMENT_DELIVERY_LOG] as DeliveryTraceabilityFieldValue;
            DeliveryTraceabilityFieldValue traceabilityEntries = null;
            XmlSerializer tSerializer = new XmlSerializer(typeof(DeliveryTraceabilityEntry));
            StringWriter sWriter = null;

            if (traceabiltyFieldValue == null) return;

            foreach (var entry in traceabiltyFieldValue.Entries)
            {
                if (entry.DateTime != entryDate)
                {
                    sWriter = new StringWriter();
                    tSerializer.Serialize(sWriter, entry);
                    if (traceabilityEntries == null)
                        traceabilityEntries = new DeliveryTraceabilityFieldValue(sWriter.ToString());
                    else
                        traceabilityEntries.Add(sWriter.ToString());
                }
            }

            input[CustomSiteColumns.FIELD_DOCUMENT_DELIVERY_LOG] = traceabiltyFieldValue;

        }

        private static void removeDocumentLog(SPListItem input, DateTime entryDate)
        {
            DocumentTraceabilityFieldValue traceabiltyFieldValue = input[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] as DocumentTraceabilityFieldValue;
            DocumentTraceabilityFieldValue traceabilityNewValue = null;
            XmlSerializer tSerializer = new XmlSerializer(typeof(TraceabilityEntry));
            StringWriter sWriter = null;

            if (traceabiltyFieldValue == null) return;

            var entries = (from entry in traceabiltyFieldValue.Entries
                           where entry.EntryDate != entryDate
                           orderby entryDate ascending
                           select entry);

            foreach (var entry in traceabiltyFieldValue.Entries)
            {
                if (entry.EntryDate != entryDate)
                {
                    sWriter = new StringWriter();
                    tSerializer.Serialize(sWriter, entry);
                    if (traceabilityNewValue == null)
                        traceabilityNewValue = new DocumentTraceabilityFieldValue(sWriter.ToString());
                    else
                        traceabilityNewValue.Add(sWriter.ToString());
                }
            }

            input[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] = traceabiltyFieldValue;
        }

        public static void Log(this SPListItem input,
                               string subsection,
                               DateTime entryDate,
                               TraceableOperation operation,
                               string user, string description)
        {
            XmlSerializer tSerializer = new XmlSerializer(typeof(TraceabilityEntry));
            StringWriter sWriter = new StringWriter();
            TraceabilityEntry entry = new TraceabilityEntry
            {
                Subsection = subsection,
                EntryDate = entryDate,
                Operation = operation,
                User = user,
                Description = description
            };

            tSerializer.Serialize(sWriter, entry);

            DocumentTraceabilityFieldValue traceabiltyFieldValue = input[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] as DocumentTraceabilityFieldValue;
            if (traceabiltyFieldValue == null)
                traceabiltyFieldValue = new DocumentTraceabilityFieldValue(sWriter.ToString());
            else
                traceabiltyFieldValue.Add(sWriter.ToString());
            input[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] = traceabiltyFieldValue;
        }


        public static IEnumerable<TraceabilityEntry> GetLog(this SPFile input)
        {
            DocumentTraceabilityFieldValue traceabiltyFieldValue = input.Item[CustomSiteColumns.FIELD_DOCSET_TRACEABILITY] as DocumentTraceabilityFieldValue;
            return traceabiltyFieldValue == null ? null : traceabiltyFieldValue.Entries;
        }

        public static string[] getItemContentType(int[] selectIds, string listId)
        {
            SPList currentList = SPContext.Current.Web.Lists[new Guid(listId)];
            if (currentList.BaseTemplate.ToString() != GlobalConstants.GLOBAL_USER_LIBRARY_TEMPLATE)
                return new string[0];

            SPQuery query = new SPQuery();
            query.Query = string.Format(@"
                            <Where>
                                <In>
                                   <FieldRef Name='ID'/>
                                    <Values>
                                    {0}
                                    </Values> 
                                  </In>
                               </Where> 
                            ", getFilters(selectIds));
            query.ViewFields = string.Format(@"<FieldRef Name='" + CustomSiteColumns.FIELD_DOCUMENT_STATUS + "' /><FieldRef Name='{0}'/><FieldRef Name='Document_Category' />", UserLibraryHelper.ContentTypeFieldName);
            
            SPListItemCollection result = currentList.GetItems(query);
            var r = (from item in result.OfType<SPListItem>()
                     select new RibbonObjectEntity
                     {
                         Id = item["ID"].ToString(),
                         Category = item["Document_Category"] == null ? string.Empty : ((TaxonomyFieldValue)item["Document_Category"]).Label,
                         ContentType = item[SPBuiltInFieldId.ContentType].ToString(),
                         Document_Status = item[CustomSiteColumns.FIELD_DOCUMENT_STATUS] == null ? string.Empty : ((TaxonomyFieldValue)item[CustomSiteColumns.FIELD_DOCUMENT_STATUS]).Label
                     });
            r = vbFilterSelected(r);
            return (from selected in r
                    select selected.ContentType).ToArray();
        }

        private static IEnumerable<RibbonObjectEntity> vbFilterSelected(IEnumerable<RibbonObjectEntity> selectedItems)
        {
            var exist = (from selected in selectedItems
                         where selected.Category == "VB" || selected.Document_Status == GlobalConstants.METADATA_TERM_STATUS_SOLICITUD_ANULAR
                         select selected).FirstOrDefault();
            if (exist == null)
                return selectedItems;
            else
                return new List<RibbonObjectEntity>();

        }

        private static string getFilters(int[] ids)
        {
            string filters = string.Empty;
            foreach (int i in ids)
            {
                filters += "<Value Type='Counter'>" + i + "</Value>";
            }
            return filters;
        }
    }

    public class RibbonObjectEntity
    {
        public string Id { get; set; }
        public string Category { get; set; }
        public string ContentType { get; set; }
        public string Document_Status { get; set; }
    }
}
